package logger

import (
	"fmt"
	"os"
	"runtime"
	"time"
)

type LogInfo struct {
	// DateTime string
	// File     string
	// Line     int
	Level   int
	LogFile string
	Prefix  bool
}

const (
	LEVEL_DEBUG = iota
	LEVEL_INFO
	LEVEL_WARN
	LEVEL_ERROR
)

const (
	gray   = 30
	red    = 31
	green  = 32
	yellow = 33
	blue   = 34
	purple = 35
	cyan   = 36
	white  = 37
)

// SetPrefix 设置是否启用日志前缀
// 参数:
//
//	enable - 布尔值，true表示启用前缀，false表示禁用前缀
func (log *LogInfo) SetPrefix(enable bool) {
	log.Prefix = enable
}

// SetLevel 函数用于设置日志级别。
// 注意事项：
//
//	如果传入的 level 参数为空，则默认将日志级别设置为 LEVEL_DEBUG。
//	如果传入的 level 参数不为空，则将日志级别设置为 level[0]。
func (log *LogInfo) SetLevel(level ...int) {
	if len(level) == 0 {
		log.Level = LEVEL_DEBUG
	} else {
		log.Level = level[0]
	}
}

// SetLogFile 函数用于设置日志文件的路径。
func (log *LogInfo) SetLogFile(filename ...string) {
	if len(filename) == 0 {
		log.LogFile = ""
	} else {
		log.LogFile = filename[0]
	}
}

// getLogInfo 函数返回 LogInfo 结构体
// LogInfo 结构体包含日志信息，如日期时间、文件名、行号、日志级别和日志文件
func GetLogInfo() *LogInfo {
	mylog := &LogInfo{
		// DateTime: now.Format("2006-01-02 15:04:05"),
		// File:     file,
		// Line:     line,
		Level:   LEVEL_DEBUG,
		LogFile: "",
		Prefix:  false,
	}
	// now := time.Now()
	// _, file, line, _ := runtime.Caller(3) // 获取当前函数的调用者信息
	return mylog
}

func (log *LogInfo) getRuntimeInfo() (dateTime, file string, line int) {
	now := time.Now()
	dateTime = now.Format("2006-01-02 15:04:05")
	_, file, line, _ = runtime.Caller(4)
	return dateTime, file, line
}

// makeLog 函数根据给定的格式字符串生成一个带有日志信息的字符串
func (log *LogInfo) makeLog(format string) (newstr string) {
	// loginfo = getLogInfo()
	_date, _file, _line := log.getRuntimeInfo()
	if log.Prefix {
		newstr = fmt.Sprintf("[%s] %s:%d ->%s\n", _date, _file, _line, format)
	} else {
		newstr = fmt.Sprint(format)
	}
	return newstr
}

// colorLog 函数用于根据给定的颜色和格式字符串输出彩色日志
// 参数：
//
//	format string：需要输出的日志格式字符串
//	color int：日志的颜色编码，对应 ANSI 转义序列
func (log *LogInfo) colorLog(format string, color int) string {
	format = log.makeLog(format)
	fmt.Printf("\033[1;%dm%s\033[0m", color, format)
	return format
}

// Printf 函数根据给定的格式化字符串和参数生成一个字符串，并将其以灰色输出到日志中
//
// 参数:
//
//	format: 格式化字符串
//	args: 可变参数列表，根据format格式化
func (log *LogInfo) Printf(format string, args ...any) {
	str := fmt.Sprintf(format, args...)
	if log.Level <= LEVEL_DEBUG {
		log.colorLog(str, gray)
	}
}

// Println 是一个可变参数函数，用于打印格式化的日志信息。
// 参数 args 是可变参数，表示要打印的内容。
// 函数内部会将参数转化为字符串并打印到控制台，并且会将打印的内容进行灰色着色处理。
func (log *LogInfo) Println(args ...any) {
	str := fmt.Sprint(args...) + "\n"
	if log.Level <= LEVEL_DEBUG {
		log.colorLog(str, gray)
	}
}

// Fatal 函数用于打印错误信息并退出程序
//
//	Fatal 函数首先使用 fmt.Sprintf 将格式化字符串和参数拼接成一个字符串，
//	然后使用 colorLog 函数以红色显示该字符串，最后通过 os.Exit(0) 退出程序
func (log *LogInfo) Fatal(format string, args ...interface{}) {
	str := fmt.Sprintf(format, args...) + "\n"
	log.colorLog(str, red)
	os.Exit(0)
}

// Debug 函数用于在调试级别输出信息
func (log *LogInfo) Debug(format ...any) string {
	if log.Level <= LEVEL_DEBUG {
		return log.colorLog(fmt.Sprint(format...)+"\n", gray)
	}
	return ""
}

// Info 函数用于根据日志级别输出信息级别的日志
func (log *LogInfo) Info(format ...any) string {
	if log.Level <= LEVEL_INFO {
		return log.colorLog(fmt.Sprint(format...)+"\n", blue)
	}
	return ""
}

// Warn 根据日志级别输出警告信息
func (log *LogInfo) Warn(format ...any) string {
	if log.Level <= LEVEL_WARN {
		return log.colorLog(fmt.Sprint(format...)+"\n", yellow)

	}
	return ""
}

// Error 根据提供的格式字符串生成错误级别的日志消息。
func (log *LogInfo) Error(format ...any) string {
	if log.Level <= LEVEL_ERROR {
		return log.colorLog(fmt.Sprint(format...)+"\n", red)
	}
	return ""
}

// ColorGray 函数将传入的格式字符串转换为灰色
func (log *LogInfo) ColorGray(format ...any) string {
	str := fmt.Sprint(format...) + "\n"
	return log.colorLog(str, 30)
}

// ColorRed 函数将传入的字符串以红色输出
func (log *LogInfo) ColorRed(format ...any) string {
	str := fmt.Sprint(format...) + "\n"
	return log.colorLog(str, 31)
}

// ColorGreen 将给定的字符串格式化为绿色输出
func (log *LogInfo) ColorGreen(format ...any) string {
	str := fmt.Sprint(format...) + "\n"
	return log.colorLog(str, 32)
}

// ColorYellow 函数接受一个字符串参数 format，并将其转换为黄色文本
func (log *LogInfo) ColorYellow(format ...any) string {
	str := fmt.Sprint(format...) + "\n"
	return log.colorLog(str, 33)
}

// ColorBlue 函数接收一个字符串格式的参数，并返回一个以蓝色显示的字符串
func (log *LogInfo) ColorBlue(format ...any) string {
	str := fmt.Sprint(format...) + "\n"
	return log.colorLog(str, 34)
}

// ColorMagenta 函数将输入的字符串格式化为洋红色的文本。
func (log *LogInfo) ColorMagenta(format ...any) string {
	str := fmt.Sprint(format...) + "\n"
	return log.colorLog(str, 35)
}

// ColorCyan 将输入字符串按照青色格式输出
func (log *LogInfo) ColorCyan(format ...any) string {
	str := fmt.Sprint(format...) + "\n"
	return log.colorLog(str, 36)
}

// ColorWhite 函数将传入的字符串格式化为白色，并返回格式化后的字符串。
func (log *LogInfo) ColorWhite(format ...any) string {
	str := fmt.Sprint(format...) + "\n"
	return log.colorLog(str, 37)
}

var Log = GetLogInfo()
